package edu.unice.simul.modele.moteur;

import java.util.List;

import edu.unice.simul.conf.GeneralSettings;
import edu.unice.simul.modele.contenus.Contenu;
import edu.unice.simul.modele.contenus.immobiles.Mur;
import edu.unice.simul.modele.contenus.mobiles.Humain;
import edu.unice.simul.util.Dim;

/**
 * Calcul les nouvelles coordonnées de l'humain en appliquant la relation de la
 * dynamique
 * 
 * @author runigo
 * 
 */

public class Calcul {
	private Humain h;

	private double x, y; // mémorisation des coordonnées
	private double xVS, yVS; // Vitesse souhaitee réduite.
	private double xFC, yFC; // Forces de contacts réduite.

	public double getxVS() {
		return xVS;
	}

	public void setxVS(double xVS) {
		this.xVS = xVS;
	}

	public double getyVS() {
		return yVS;
	}

	public void setyVS(double yVS) {
		this.yVS = yVS;
	}

	public double getxFC() {
		return xFC;
	}

	public void setxFC(double xFC) {
		this.xFC = xFC;
	}

	public double getyFC() {
		return yFC;
	}

	public void setyFC(double yFC) {
		this.yFC = yFC;
	}

	public Calcul() {
	}

	public void calculer(Humain h) {
		this.h = h;
		x = h.getAbscisse();
		y = h.getOrdonnee();

		calcul_dt_2VsSurTau(h);
		calcul_dt_2FcSurMasse(h);
		calculRelationFondamentaleDynamique(h);

		if (GeneralSettings.DEBUG)
			System.err.println(h.getAbscisse() + "," + h.getDirectionSouhaitee());

		sauvegarder(h);
	}

	/**
	 * Affectation des anciennes coordonnées Réinitialisation à 0 des forces de
	 * contacts
	 * 
	 * @param h
	 */
	public void sauvegarder(Humain h) {
		h.setAncienAbs(x);
		h.setAncienOrd(y);

		h.setForceContactX(0);
		h.setForceContactY(0);
	}

	/**
	 * Applique la relation de la dynamique aux coordonnées de l'humain
	 * 
	 * @param h
	 */
	public void calculRelationFondamentaleDynamique(Humain h) {
		double abs = ((2 - h.getDtSurTau()) * x) - (1 - h.getDtSurTau())
				* h.getAncienAbs() + xVS + xFC;
		
		if (abs > h.getTaillePiece().getX())
			abs = h.getTaillePiece().getX() - .001;
		else if (abs < 0)
			abs = 0;

		double ord = ((2 - h.getDtSurTau()) * y) - (1 - h.getDtSurTau())
				* h.getAncienOrd() + yVS + yFC;

		if (ord > h.getTaillePiece().getY())
			ord = h.getTaillePiece().getY() - .001;
		else if (ord < 0)
			ord = 0;

		boolean autorise = true;
		List<Contenu> content = h.getPiece().getContenuAt(
				new Dim((int) abs, (int) ord));

		for (Contenu c : content)
			if (c instanceof Mur)
				autorise = false;

		if (autorise) {
			h.setAbscisse(abs);
			h.setOrdonnee(ord);
		}
	}

	/**
	 * Calcul préliminaire de la force de contact réduite en fonction de dt et de
	 * la masse
	 * 
	 * @param h
	 */
	public void calcul_dt_2FcSurMasse(Humain h) {
		xFC = h.getDt2SurM() * h.getForceContactX();
		yFC = h.getDt2SurM() * h.getForceContactY();
	}

	/**
	 * Calcul preliminaire de la vitesse souhaité réduite en fonction de dt et de
	 * l'agressivité
	 * 
	 * @param h
	 */
	public void calcul_dt_2VsSurTau(Humain h) {
		xVS = h.getDt2SurTau() * h.getVitesseSouhaitee()
				* Math.cos(h.getDirectionSouhaitee());
		yVS = h.getDt2SurTau() * h.getVitesseSouhaitee()
				* Math.sin(h.getDirectionSouhaitee());
	}
}
